package spring.demo.security.userService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import spring.demo.security.dao.ResourceRepository;
import spring.demo.security.dao.ResourceRoleRepository;
import spring.demo.security.dao.RoleRepository;
import spring.demo.security.entity.SysResource;
import spring.demo.security.entity.SysResourceRole;
import spring.demo.security.entity.SysRole;
import sun.security.util.AuthResources_ja;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 *
 * @author td
 * @date 2017/10/11
 */
public class CusotmInvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource {

    @Autowired
    private ResourceRepository resourceRepository;

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private ResourceRoleRepository resourceRoleRepository;

    private static Map<String, Collection<ConfigAttribute>> resourceMap = null;

    /**
     * 该方法是根据用户请求的url资源，获取权限的集合
     * @param o 请求的url
     * @return
     * @throws IllegalArgumentException
     */
    @Override
    public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
        FilterInvocation filterInvocation = (FilterInvocation) o;
        if (resourceMap == null) {
            loadResourceDefine();
        }
        Iterator<String> iterator = resourceMap.keySet().iterator();
        while (iterator.hasNext()) {
            String resUrl = iterator.next();
            RequestMatcher requestMatcher = new AntPathRequestMatcher(resUrl);
            if (requestMatcher.matches(filterInvocation.getHttpRequest())) {
                return resourceMap.get(resUrl);
            }
        }
        return null;
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return false;
    }



    // @postConstruct注解注释的方法会在构造函数之后 init方法之前运行。该方法主要是将 资源和权限放到一个 Map<String, Collection<ConfigAttribute>> 集合中
    // 资源url为key，权限为Collection<ConfigAttribute>
    @PostConstruct
    private void loadResourceDefine() {  /*<span style="color:#33cc00;"> //一定要加上<span style="font-family: Arial, Helvetica, sans-serif;">@PostConstruct注解</span></span>
    <span style="color:#33cc00;">// 在Web服务器启动时，提取系统中的所有权限。</span>  */
        List<SysRole> list = roleRepository.findAll();
        List<String> query = new ArrayList<>();
        resourceMap = new HashMap<String,Collection<ConfigAttribute>>(16);


        for (SysRole sysRole:list) {
            query.add(sysRole.getName());
            // 角色名--权限名
            String auth = sysRole.getName();
            ConfigAttribute ca = new SecurityConfig(auth);
            List<String> resourceUrl = new ArrayList<>();
            //查找角色名对应的资源url
            List<SysResourceRole> sysResourceRoles = resourceRoleRepository.findByRoleId(sysRole.getId());
            for (SysResourceRole sysResourceRole:sysResourceRoles) {
                int resourceId = Integer.parseInt(sysResourceRole.getResourceId());
                SysResource sysResource = resourceRepository.findById(resourceId);
                resourceUrl.add(sysResource.getResourceName());
                if (resourceMap.containsKey(sysResource.getResourceName())) {
                    Collection<ConfigAttribute> attributeCollection = resourceMap.get(sysResource.getResourceName());
                    attributeCollection.add(ca);
                  //  resourceMap.put(sysResource.getResourceName(),)
                    resourceMap.put(sysResource.getResourceName(),attributeCollection);

                }else {
                    Collection<ConfigAttribute> attributeCollection = new ArrayList<>();
                    attributeCollection.add(ca);
                    resourceMap.put(sysResource.getResourceName(),attributeCollection);
                }
            }


            // 判断资源文件和权限的对应关系，如果已经存在相关的资源url，则要通过url为key进行提取权限集合，将权限增加到权限集合中。


        }

        /*
          应当是资源为key  权限为value。资源通常是url，权限就是那些以role为前缀的角色，一个资源可以由多个权限来访问
         */



       // List<Map<String,Object>> list =roleRepository.findAll();
 /*       List<String> query = new ArrayList<String>();
        if(list!=null && list.size()>0) {
            for(Map<String,Object> sr :list){
                //String name = sr.get("name")
                Object value = sr.get("name");
                String name = String.valueOf(value);
                query.add(name);
            }
        }
      *//*  <span style="color:#33cc00;">*//**//*
         * 应当是资源为key， 权限为value。 资源通常为url， 权限就是那些以ROLE_为前缀的角色。 一个资源可以由多个权限来访问。
         * sparta
         *//**//*</span>*//*
        resourceMap = new HashMap<String, Collection<ConfigAttribute>>();

        for (String auth : query) {
            ConfigAttribute ca = new SecurityConfig(auth);
            //List<Map<String,Object>> query1 = sResourceVODao.findByRoleName(auth);
            List<String> query1 = new ArrayList<String>();
            List<Map<String, Object>>  list1 = sResourceVODao.findByRoleName(auth);
            if(list1!=null && list1.size()>0) {
                for(Map<String, Object> map :list1){
                    Object value = map.get("resource_string");
                    String url = String.valueOf(value);
                    query1.add(url);
                }
            }
            for (String res : query1) {
                String url = res;

            *//*    <span style="color:#33cc00;">*//**//*
                 * 判断资源文件和权限的对应关系，如果已经存在相关的资源url，则要通过该url为key提取出权限集合，将权限增加到权限集合中。
                 * sparta
                 *//**//*</span>*//*
                if (resourceMap.containsKey(url)) {

                    Collection<ConfigAttribute> value = resourceMap.get(url);
                    value.add(ca);
                    resourceMap.put(url, value);
                } else {
                    Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
                    atts.add(ca);
                    resourceMap.put(url, atts);
                }

            }
        }*/



    }


}
